package com.fzsf.drawingboard.utils;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.util.Base64;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by Taijl on 2015/12/14.
 */
public class BitmapUtils {
    /**
     * 质量压缩
     *
     * @param image
     * @param maxkb
     * @return
     */
    public static Bitmap compressBitmap(Bitmap image, int maxkb) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;

        while (baos.toByteArray().length / 1024 > maxkb) { // 循环判断如果压缩后图片是否大于(maxkb)50kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            options -= 10;// 每次都减少10
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
        }

        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    /**
     * http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
     * 官网：获取压缩后的图片
     *
     * @param res
     * @param resId
     * @param reqWidth  所需图片压缩尺寸最小宽度
     * @param reqHeight 所需图片压缩尺寸最小高度
     * @return
     */
    public static Bitmap decodeSampledBitmapFromResource(Resources res,
                                                         int resId, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    /**
     * 官网：获取压缩后的图片
     *
     * @param reqWidth  所需图片压缩尺寸最小宽度
     * @param reqHeight 所需图片压缩尺寸最小高度
     * @return
     */
    public static Bitmap decodeSampledBitmapFromFile(String filepath, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filepath, options);

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filepath, options);
    }

    public static Bitmap decodeSampledBitmapFromBitmap(Bitmap bitmap,
                                                       int reqWidth, int reqHeight) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
        byte[] data = baos.toByteArray();

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(data, 0, data.length, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeByteArray(data, 0, data.length, options);
    }

    /**
     * 计算压缩比例值(改进版)
     * <p/>
     * 原版2>4>8...倍压缩
     * 当前2>3>4...倍压缩
     *
     * @param options   解析图片的配置信息
     * @param reqWidth  所需图片压缩尺寸最小宽度O
     * @param reqHeight 所需图片压缩尺寸最小高度
     * @return
     */
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int picheight = options.outHeight;
        final int picwidth = options.outWidth;

        int targetheight = picheight;
        int targetwidth = picwidth;
        int inSampleSize = 1;

        if (targetheight > reqHeight || targetwidth > reqWidth) {
            while (targetheight >= reqHeight
                    && targetwidth >= reqWidth) {

                inSampleSize += 1;
                targetheight = picheight / inSampleSize;
                targetwidth = picwidth / inSampleSize;
            }
        }
        return inSampleSize;
    }

    /**
     * 把 bitmap 转码 Base64
     *
     * @param bitmap 图片的bitmap
     * @return
     */
    public static String bitmap2Base64(Bitmap bitmap) {
        if (null == bitmap) {
            return "";
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        String img = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
        if (!bitmap.isRecycled()) {
            bitmap.recycle();
        }
        return img;
    }

    /**
     * 把base64 转成图片
     *
     * @param string
     * @return
     */
    public static Bitmap base64toBitmap(String string) {
        //将字符串转换成Bitmap类型
        Bitmap bitmap = null;
        try {
            byte[] bitmapArray;
            bitmapArray = Base64.decode(string, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    /**
     * 从给定路径加载图片
     */
    public static Bitmap loadBitmap(String imgpath) {
        if (StringUtils.isEmpty(imgpath)) {
            return null;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        Bitmap bm = null;

        // 减少内存使用量，有效防止OOM
        {
            options.inJustDecodeBounds = true;
            bm = BitmapFactory.decodeFile(imgpath, options);

            // 屏幕宽
            int Wight = ScreenUtils.getWidth();

            // 缩放比
            int ratio = options.outWidth / Wight;
            if (ratio <= 0)
                ratio = 1;
            options.inSampleSize = ratio;
            options.inJustDecodeBounds = false;
        }

        // 加载图片,并返回
        return BitmapFactory.decodeFile(imgpath, options);
    }

    /**
     * 保存照片
     *
     * @param bitmap   the current picture object
     * @param fileName the current picture name
     * @return the current capture path
     * @version 1.0.0
     */
    public static String savePictureToSdcard(Bitmap bitmap, String fileName) {
        if (bitmap == null) {
            return fileName;
        } else {
            File destFile = new File(fileName);
            if (destFile.exists()) {
                destFile.delete();
            }
            OutputStream os = null;
            try {
                os = new FileOutputStream(destFile);
                bitmap.compress(Bitmap.CompressFormat.PNG, 90, os);
                os.flush();
                os.close();
            } catch (IOException e) {
                fileName = "";
            }
        }
        return fileName;
    }

    /**
     * 读取图片属性：旋转的角度
     *
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋转图片
     *
     * @param angle
     * @param bitmap
     * @return Bitmap
     */
    public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }

    /**
     * 等比例压缩到最大值（宽或者高）
     *
     * @param filepath 图片地址
     * @param maxSize  宽高的最大值
     * @return
     */
    public static Bitmap decodeSampledBitmapFromFile(String filepath, int maxSize) {
        if (StringUtils.isEmpty(filepath) || maxSize <= 0) {
            throw new IllegalArgumentException("传入参数有误");
        }
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        int reqWidth, reqHeight;
        BitmapFactory.decodeFile(filepath, options);
        final int picheight = options.outHeight;
        final int picwidth = options.outWidth;
        if (picheight <= 960 && picwidth <= 960) {
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeFile(filepath, options);
        } else {
            if (picheight > picwidth) {
                reqHeight = maxSize;
                reqWidth = picwidth * maxSize / picheight;
            } else {
                reqWidth = maxSize;
                reqHeight = picheight * maxSize / picwidth;
            }
        }
//        Log.e("test", "新尺寸:" + reqWidth + "*" + reqHeight);
        Bitmap bitmap = decodeSampledBitmapFromFile(filepath, 1440, 1440);
        Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
        bitmap.recycle();
        return scaledBitmap;
    }

    /**
     * 保存到本地  图片大的时候进行一次质量压缩
     *
     * @param bitmap   图片
     * @param fileName 保存地址
     * @param maxSize  压缩一次的大小界限 （大于 就 压一次50%）
     * @return
     */
    public static String savePictureToSdcard(Bitmap bitmap, String fileName, int maxSize) {
        if (bitmap == null) {
            return fileName;
        } else {
            File destFile = new File(fileName);
            if (destFile.exists()) {
                destFile.delete();
            }
            OutputStream os = null;
            try {
                os = new FileOutputStream(destFile);
                long bitmapsize = getBitmapsize(bitmap);
//                Log.e("test", "缩之后的大小  " + bitmapsize);
                if (bitmapsize > maxSize) {
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);
                } else {
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
                }
                os.flush();
                os.close();
                bitmap.recycle();
            } catch (IOException e) {
                fileName = "";
            }
        }
        return fileName;
    }

    /**
     * 获取图片字节大小
     *
     * @param bitmap
     * @return
     */
    private static long getBitmapsize(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        final int size = baos.toByteArray().length / 1024;
        baos = null;
        return size;
    }

    /*给定一个Bitmap，进行保存*/
    public static String saveJpeg(Bitmap bm) {
        String savePath = FileAccessor.IMESSAGE_IMAGE;
        File folder = new File(savePath);
        if (!folder.exists()) {
            return null;
        }
        long dataTake = System.currentTimeMillis();
        String jpegName = savePath + "/" + dataTake + ".jpg";
        Log.i("saveJpeg", "saveJpeg:jpegName--" + jpegName);
        try {
            FileOutputStream fout = new FileOutputStream(jpegName);
            BufferedOutputStream bos = new BufferedOutputStream(fout);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
            Log.i("saveJpeg", "saveJpeg：存储完毕！");
            return jpegName;
        } catch (IOException e) {
            Log.i("saveJpeg", "saveJpeg:存储失败！");
            e.printStackTrace();
            return null;
        }
    }

    /*给定一个Bitmap，进行保存*/
    public static String savePng(Bitmap bm) {
        String savePath = FileAccessor.IMESSAGE_IMAGE;
        File folder = new File(savePath);
        if (!folder.exists()) {
            return null;
        }
        long dataTake = System.currentTimeMillis();
        String jpegName = savePath + "/" + dataTake + ".png";
        Log.i("saveJpeg", "saveJpeg:jpegName--" + jpegName);
        try {
            FileOutputStream fout = new FileOutputStream(jpegName);
            BufferedOutputStream bos = new BufferedOutputStream(fout);
            bm.compress(Bitmap.CompressFormat.PNG, 100, bos);
            bos.flush();
            bos.close();
            Log.i("saveJpeg", "saveJpeg：存储完毕！");
            return jpegName;
        } catch (IOException e) {
            Log.i("saveJpeg", "saveJpeg:存储失败！");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * bitmap中的透明色用白色替换
     *
     * @param bitmap
     * @return
     */
    public static Bitmap changeColor(Bitmap bitmap) {
        if (bitmap == null) {
            return null;
        }
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        int[] colorArray = new int[w * h];
        int n = 0;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                int color = getMixtureWhite(bitmap.getPixel(j, i));
                colorArray[n++] = color;
            }
        }
        return Bitmap.createBitmap(colorArray, w, h, Bitmap.Config.ARGB_8888);
    }

    /**
     * 获取和白色混合颜色
     *
     * @return
     */
    private static int getMixtureWhite(int color) {
        int alpha = Color.alpha(color);
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.rgb(getSingleMixtureWhite(red, alpha), getSingleMixtureWhite

                        (green, alpha),
                getSingleMixtureWhite(blue, alpha));
    }

    /**
     * 获取单色的混合值
     *
     * @param color
     * @param alpha
     * @return
     */
    private static int getSingleMixtureWhite(int color, int alpha) {
        int newColor = color * alpha / 255 + 255 - alpha;
        return newColor > 255 ? 255 : newColor;
    }
}
